@page "/visitor/preregisters"


@using Blazor.Server.UI.Services
@using Blazor.Server.UI.Pages.CheckinPoints
@using CleanArchitecture.Blazor.Application.Features.VisitorHistories.DTOs
@using CleanArchitecture.Blazor.Application.Features.VisitorHistories.Queries.GetAll
@using CleanArchitecture.Blazor.Application.Features.Visitors.Commands.Create
@using CleanArchitecture.Blazor.Application.Features.Visitors.Commands.Delete
@using CleanArchitecture.Blazor.Application.Features.Visitors.DTOs
@using CleanArchitecture.Blazor.Application.Features.Visitors.Queries.Pagination
@using CleanArchitecture.Blazor.Application.Features.Visitors.Commands.AddEdit
@using CleanArchitecture.Blazor.Application.Features.Visitors.Queries.Search
@using HashidsNet
@using Net.Codecrete.QrCodeGenerator
@using SixLabors.ImageSharp
@using SixLabors.ImageSharp.Formats
@using SixLabors.ImageSharp.Processing
@inject IJSRuntime JS
@inject IStringLocalizer<Visitors> L
@attribute [Authorize(Policy = Permissions.Visitors.PreRegisters)]
<PageTitle>@Title</PageTitle>
<style>
    .mud-table-toolbar {
        height: 84px !important;
    }
</style>
<ErrorBoundary>
    <ChildContent>
        <MudGrid>
            <MudItem xs="12" sm="7">
                <MudPaper Class="pa-4 mt-4">
                    <MudTextField @bind-Value="_searchString" Label="@L["Search for visitor's email or phone number."]" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentIcon="@Icons.Filled.Search" AdornmentColor="MudBlazor.Color.Primary" OnAdornmentClick="OnSearch" />
                </MudPaper>
                <MudPaper Class="pa-4 mt-4">
                    <MudForm Model="model" @ref="form" Validation="@(modelValidator.ValidateValue)">
                        <MudGrid>
                            <MudItem xs="12" sm="6" md="4">
                                <MudTextField Label="@L["Visitor's Name"]" @bind-Value="model.Name"
                                              For="@(() => model.Name)"
                                              Disabled="@(model.Apppoved==true)"
                                              Required="true"
                                              RequiredError="@L["product name is required!"]">
                                </MudTextField>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="8">
                                <MudTextField Label="@L["Company Name"]"
                                              For="@(() => model.CompanyName)"
                                              Disabled="@(model.Apppoved==true)"
                                              @bind-Value="model.CompanyName"></MudTextField>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <MudTextField Label="@L["License Plate Number"]"
                                              For="@(() => model.LicensePlateNumber)"
                                              Disabled="@(model.Apppoved==true)"
                                              @bind-Value="model.LicensePlateNumber"></MudTextField>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <MudTextField Label="@L["Email"]"
                                              For="@(() => model.Email)"
                                              Disabled="@(model.Apppoved==true)"
                                              Required="true"
                                              RequiredError="@L["email is required!"]"
                                              @bind-Value="model.Email"></MudTextField>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <MudTextField Label="@L["Phone Number"]"
                                              For="@(() => model.PhoneNumber)"
                                              Disabled="@(model.Apppoved==true)"
                                              Required="true"
                                              RequiredError="@L["Phone Number is required!"]"
                                              @bind-Value="model.PhoneNumber"></MudTextField>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <MudTextField Label="@L["Identification No."]"
                                              For="@(() => model.IdentificationNo)"
                                              Disabled="@(model.Apppoved==true)"
                                              Required="true"
                                              RequiredError="@L["Identification No. is required!"]"
                                              @bind-Value="model.IdentificationNo"></MudTextField>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <PicklistAutocomplete Picklist="Picklist.Gender"
                                                      Disabled="@(model.Apppoved==true)"
                                                      Label="@L["Gender"]"
                                                      For="@(() => model.Gender)"
                                                      ResetValueOnEmptyText="true"
                                                      @bind-Value="model.Gender"></PicklistAutocomplete>
                            </MudItem>

                            <MudItem xs="12" sm="6" md="4">
                                <PicklistAutocomplete Picklist="Picklist.Purpose"
                                                      Label="@L["Purpose"]"
                                                      Disabled="@(model.Apppoved==true)"
                                                      Required="true"
                                                      RequiredError="@L["purpose is required!"]"
                                                      For="@(() => model.Purpose)"
                                                      ResetValueOnEmptyText="true"
                                                      @bind-Value="model.Purpose"></PicklistAutocomplete>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <EmployeeAutocomplete Label="@L["Select Employee"]"
                                                      Required="true"
                                                      Disabled="@(model.Apppoved==true)"
                                                      RequiredError="@L["employee is required!"]"
                                                      For="@(() => model.EmployeeId)"
                                                      ResetValueOnEmptyText="true"
                                                      @bind-Value="model.EmployeeId"></EmployeeAutocomplete>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <MudDatePicker Label="@L["Expected Date"]"
                                               Disabled="@(model.Apppoved==true)"
                                               Required="true"
                                               RequiredError="@L["expected date is required!"]"
                                               For="@(() => model.ExpectedDate)"
                                               @bind-Date="model.ExpectedDate"></MudDatePicker>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="4">
                                <MudTimePicker Label="@L["Expected Time"]"
                                               Required="true"
                                               Disabled="@(model.Apppoved==true)"
                                               RequiredError="@L["expected time is required!"]"
                                               AmPm="true" TimeFormat="h:mm tt"
                                               For="@(() => model.ExpectedTime)"
                                               @bind-Time="model.ExpectedTime"></MudTimePicker>
                            </MudItem>
                            <MudItem xs="12" sm="12">
                                <SiteAutocomplete Label="@L["Select Site - Address"]"
                                                  Disabled="@(model.Apppoved==true)"
                                                  For="@(() => model.SiteId)"
                                                  Required="true" RequiredError="@L["site - address is required!"]"
                                                  @bind-Value="model.SiteId"></SiteAutocomplete>
                            </MudItem>
                            <MudItem xs="12" sm="12">
                                <MudTextField Label="@L["Comment"]"
                                              For="@(() => model.Comment)"
                                              Lines="2"
                                              Disabled="@(model.Apppoved==true)"
                                              @bind-Value="model.Comment"></MudTextField>
                            </MudItem>


                            <MudItem xs="12" sm="6" md="4">
                                <MudCheckBox Label="@L["Has apppoved"]"
                                             Disabled="@(model.Apppoved==true)"
                                             For="@(() => model.Apppoved)" ReadOnly="true"
                                             @bind-Checked="model.Apppoved"></MudCheckBox>
                            </MudItem>
                            <MudItem xs="12" sm="6" md="8">
                                <MudTextField Label="@L["Approval Outcome"]"
                                              Disabled="@(model.Apppoved==true)"
                                              For="@(() => model.ApprovalOutcome)"
                                              @bind-Value="model.ApprovalOutcome"></MudTextField>
                            </MudItem>
                            <MudItem>
                                <div class="d-flex gap-3 flex-wrap">
                                    <MudCard Style="width:200px">
                                        <MudCardMedia Image="@model.Avatar" Height="200" />
                                        <MudCardContent>
                                            <MudText Typo="Typo.body2">@L["The photo is used for intelligent face recognition"]</MudText>
                                        </MudCardContent>
                                        <MudCardActions>
                                            <InputFile id="photoInput" OnChange="UploadAvatarPhoto" hidden accept=".jpg, .jpeg, .png" />
                                            <MudButton HtmlTag="label" for="photoInput" Disabled="@(model.Apppoved==true)" Variant="Variant.Text" Color="MudBlazor.Color.Primary">@L["Upload a Photo"]</MudButton>
                                        </MudCardActions>
                                    </MudCard>
                                    <MudCard Style="width:200px">
                                        <MudCardMedia Image="@model.HealthCode" Height="200" />
                                        <MudCardContent>
                                            <MudText Typo="Typo.body2">@L["Only green codes are allowed"]</MudText>
                                        </MudCardContent>
                                        <MudCardActions>
                                            <InputFile id="healthcodeInput" OnChange="UploadHealthCodePhoto" hidden accept=".jpg, .jpeg, .png" />
                                            <MudButton HtmlTag="label" for="healthcodeInput" Disabled="@(model.Apppoved==true)" Variant="Variant.Text" Color="MudBlazor.Color.Primary">@L["Upload a health code"]</MudButton>
                                        </MudCardActions>
                                    </MudCard>
                                    <MudCard Style="width:200px">
                                        <MudCardMedia Image="@model.TripCode" Height="200" />
                                        <MudCardContent>
                                            <MudText Typo="Typo.body2">@L["Make sure you haven't been to a medium-high risk area for 14 days"]</MudText>
                                        </MudCardContent>
                                        <MudCardActions>
                                            <InputFile id="tripcodeInput" OnChange="UploadTripCodePhoto" hidden accept=".jpg, .jpeg, .png" />
                                            <MudButton HtmlTag="label" for="tripcodeInput" Disabled="@(model.Apppoved==true)" Variant="Variant.Text" Color="MudBlazor.Color.Primary">@L["Upload a trip code"]</MudButton>
                                        </MudCardActions>
                                    </MudCard>
                                    <MudCard Style="width:200px">
                                        <MudCardMedia Image="@model.NucleicAcidTestReport" Height="200" />
                                        <MudCardContent>
                                            <MudText Typo="Typo.body2">@L["Upload a nucleic acid test report"]</MudText>
                                        </MudCardContent>
                                        <MudCardActions>
                                            <InputFile id="testreportInput" OnChange="UploadTestReportPhoto" hidden accept=".jpg, .jpeg, .png" />
                                            <MudButton HtmlTag="label" for="testreportInput" Disabled="@(model.Apppoved==true)" Variant="Variant.Text" Color="MudBlazor.Color.Primary">@L["Upload a nucleic acid test report"]</MudButton>
                                        </MudCardActions>
                                    </MudCard>
                                </div>
                            </MudItem>
                            <MudItem xs="12" sm="6">
                                <MudCheckBox Label="@L["Agree Privacy Policy"]"
                                             For="@(() => model.PrivacyPolicy)"
                                             Disabled="@(model.Apppoved==true)"
                                             Required="true" RequiredError="You must agree"
                                             @bind-Checked="model.PrivacyPolicy"></MudCheckBox>
                            </MudItem>
                            <MudItem xs="12" sm="6">
                                <MudCheckBox Label="@L["I promise the truth"]"
                                             For="@(() => model.Promise)"
                                             Disabled="@(model.Apppoved==true)"
                                             Required="true" RequiredError="You must promise"
                                             @bind-Checked="model.Promise"></MudCheckBox>
                            </MudItem>
                        </MudGrid>
                    </MudForm>
                </MudPaper>
                <MudPaper Class="d-flex pa-4 mt-4">
                    <MudButton Variant="Variant.Filled" Color="MudBlazor.Color.Secondary" DisableElevation="true" OnClick="@(()=>form.Reset())" Class="ml-auto mx-2">@L["Reset"]</MudButton>
                    <MudButton Variant="Variant.Filled" Disabled="@(model.Id>0)" DisableElevation="true" OnClick="Submit">@L["Submit"]</MudButton>
                </MudPaper>
            </MudItem>
            <MudItem xs="12" sm="5">

                <div class="d-flex flex-column justify-center align-content-center">
                    <MudPaper Class="pa-4 mt-4" Style="width:320px">
                        <MudTextField @bind-Value="_searchQRcode" Label="@L["Search my QRcode"]" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentIcon="@Icons.Filled.Search" AdornmentColor="MudBlazor.Color.Primary" OnAdornmentClick="OnSearchQRcode" />
                    </MudPaper>
                    <MudCard Class="pa-4 mt-4" Style="width:320px">
                        @if (_notfound)
                        {
                            <MudAlert Severity="MudBlazor.Severity.Error">@L["Not found visitor's information"]</MudAlert>
                        }
                        <MudCardHeader>
                            <CardHeaderContent>
                                <MudText Typo="Typo.h6">@L["Pass Code"]: @_visitorWithQRCode.PassCode</MudText>
                            </CardHeaderContent>
                        </MudCardHeader>
                        <MudCardMedia Image="@_visitorWithQRCode.QrCode" Height="288" />
                        <MudCardContent>
                            <MudForm>
                                <MudTextField For="@(() => _visitorWithQRCode.Name)" Value="@_visitorWithQRCode.Name" Label="@L["Visitor's Name"]" ReadOnly="true" />
                                <MudTextField For="@(() => _visitorWithQRCode.CompanyName)" Value="@_visitorWithQRCode.CompanyName" Label="@L["Company Name"]" ReadOnly="true" />
                                <MudTextField For="@(() => _visitorWithQRCode.LicensePlateNumber)" Value="@_visitorWithQRCode.LicensePlateNumber" Label="@L["License Plate Number"]" ReadOnly="true" />
                                <MudTextField For="@(() => _visitorWithQRCode.Purpose)" Value="@_visitorWithQRCode.Purpose" Label="@L["Purpose"]" ReadOnly="true" />
                                <MudTextField For="@(() => _visitorWithQRCode.Employee)" Value="@_visitorWithQRCode.Employee" Label="@L["Employee"]" ReadOnly="true" />
                                <MudTextField For="@(() => _visitorWithQRCode.ExpectedDate)" Value="@_visitorWithQRCode.ExpectedDate" Label="@L["Expected Date"]" ReadOnly="true" />
                                <MudTextField For="@(() => _visitorWithQRCode.ExpectedTime)" Value="@_visitorWithQRCode.ExpectedTime" Label="@L["Expected Time"]" ReadOnly="true" />
                            </MudForm>
                        </MudCardContent>
                        <MudCardActions>
                            <MudText Class="mr-2">@L["Survey feedback"]</MudText>
                            <MudRating SelectedValue="3" />
                        </MudCardActions>
                    </MudCard>

                    <MudCard Class="pa-4 mt-4" Style="width:320px">
                        <MudCardHeader>
                            <CardHeaderContent>
                                <MudText Typo="Typo.h6">@L["Check-in Histories"] (0)</MudText>
                            </CardHeaderContent>
                        </MudCardHeader>
                        <MudCardContent>
                            @if (_visitorHistories.Count > 0)
                            {
                                <MudTimeline>
                                    @foreach (var item in _visitorHistories)
                                    {
                                        <MudTimelineItem Color="MudBlazor.Color.Info" Size="MudBlazor.Size.Small">
                                            <ItemOpposite>
                                                <MudText Color="MudBlazor.Color.Info" Typo="Typo.body1">@item.CheckinPoint</MudText>
                                            </ItemOpposite>
                                            <ItemContent>
                                                <MudText Color="MudBlazor.Color.Info" Typo="Typo.body2" GutterBottom="true">@item.TransitDateTime</MudText>
                                                <MudText>@item.Comment</MudText>
                                            </ItemContent>
                                        </MudTimelineItem>

                                    }
                                </MudTimeline>
                            }
                        </MudCardContent>
                    </MudCard>
                </div>

            </MudItem>
        </MudGrid>
    </ChildContent>
    <ErrorContent>
        <CustomError Exception="context"></CustomError>
    </ErrorContent>
</ErrorBoundary>
@code {
    public string? Title { get; private set; }
    private MudForm form = default!;
    private string _searchString = string.Empty;
    private string _searchQRcode = string.Empty;
    private VisitorDto? _visitorDto = null;
    private VisitorDto? _visitorWithQRCode = new();
    private List<VisitorHistoryDto> _visitorHistories = new();
    private CreateVisitorCommandValidator modelValidator = new CreateVisitorCommandValidator();
    private CreateVisitorCommand model { get; set; } = new CreateVisitorCommand();
    private bool _notfound;
    private bool _loading;
    private bool _uploading;
    private bool _submited;
    [Inject] private IUploadService _uploadService { get; set; } = default!;
    [Inject]
    private ISender _mediator { get; set; } = default!;
    [Inject]
    private Hashids hashids { get; set; } = default!;
    [CascadingParameter]
    protected Task<AuthenticationState> AuthState { get; set; } = default!;

    protected override async Task OnInitializedAsync()
    {
        Title = L["Pre Registers"];
        model.PassCode = hashids.EncodeLong(DateTime.Now.Ticks);
        var state = await AuthState;
    }
    private async Task OnSearch()
    {
        if (string.IsNullOrEmpty(_searchString)) _visitorDto = null;
        _visitorDto = await _mediator.Send(new SearchVisitorQuery(_searchString));
        if (_visitorDto != null)
        {
            model = new CreateVisitorCommand()
                {
                    PassCode = hashids.EncodeLong(DateTime.Now.Ticks),
                    Name = _visitorDto.Name,
                    IdentificationNo = _visitorDto.IdentificationNo,
                    CompanyName = _visitorDto.CompanyName,
                    Address = _visitorDto.Address,
                    Avatar = _visitorDto.Avatar,
                    Email = _visitorDto.Email,
                    DesignationId = _visitorDto.DesignationId,
                    EmployeeId = _visitorDto.EmployeeId,
                    Gender = _visitorDto.Gender,
                    LicensePlateNumber = _visitorDto.LicensePlateNumber,
                    PhoneNumber = _visitorDto.PhoneNumber,
                    Purpose = _visitorDto.Purpose,
                    Promise = true,
                    PrivacyPolicy = true

                };
        }

    }
    private async Task OnSearchQRcode()
    {
        var visitor = await _mediator.Send(new SearchVisitorQuery(_searchQRcode));
        if (visitor is null)
        {
            _notfound = true;
            _visitorWithQRCode = new();
        }
        else
        {
            _notfound = false;
            _visitorWithQRCode = visitor;
            _visitorHistories = (await _mediator.Send(new GetByVisitorIdVisitorHistoriesQuery(_visitorWithQRCode.Id))).ToList();
        }

    }

    private async Task UploadAvatarPhoto(InputFileChangeEventArgs e)
    {
        var file = e.File;
        var filestream = file.OpenReadStream();
        var imgstream = new MemoryStream();
        await filestream.CopyToAsync(imgstream);
        imgstream.Position = 0;
        using (var outStream = new MemoryStream())
        {
            using (var image = Image.Load(imgstream, out IImageFormat format))
            {
                image.Mutate(
                   i => i.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new SixLabors.ImageSharp.Size(350, 350) }));
                image.Save(outStream, format);
                var filename = file.Name;
                var fi = new FileInfo(filename);
                var ext = fi.Extension;
                var result = await _uploadService.UploadAsync(new UploadRequest()
                    {
                        Data = outStream.ToArray(),
                        FileName = "A_" + Guid.NewGuid().ToString() + ext,
                        Extension = ext,
                        Folder = model.PassCode,
                        UploadType = UploadType.VisitorPricture
                    });
                model.Avatar = result.Replace("\\", "/");
            }
        }

        Snackbar.Add(L["Upload photo successfully"], MudBlazor.Severity.Info);

    }
    private async Task UploadHealthCodePhoto(InputFileChangeEventArgs e)
    {
        var file = e.File;
        var filestream = file.OpenReadStream();
        var imgstream = new MemoryStream();
        await filestream.CopyToAsync(imgstream);
        imgstream.Position = 0;
        using (var outStream = new MemoryStream())
        {
            using (var image = Image.Load(imgstream, out IImageFormat format))
            {
                image.Mutate(
                   i => i.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new SixLabors.ImageSharp.Size(430, 780) }));
                image.Save(outStream, format);
                var filename = file.Name;
                var fi = new FileInfo(filename);
                var ext = fi.Extension;
                var result = await _uploadService.UploadAsync(new UploadRequest()
                    {
                        Data = outStream.ToArray(),
                        FileName = "H_" + Guid.NewGuid().ToString() + ext,
                        Extension = ext,
                        Folder = model.PassCode,
                        UploadType = UploadType.VisitorPricture
                    });
                model.HealthCode = result.Replace("\\", "/");
            }
        }

        Snackbar.Add(L["Upload health code successfully"], MudBlazor.Severity.Info);

    }
    private async Task UploadTripCodePhoto(InputFileChangeEventArgs e)
    {
        var file = e.File;
        var filestream = file.OpenReadStream();
        var imgstream = new MemoryStream();
        await filestream.CopyToAsync(imgstream);
        imgstream.Position = 0;
        using (var outStream = new MemoryStream())
        {
            using (var image = Image.Load(imgstream, out IImageFormat format))
            {
                image.Mutate(
                   i => i.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new SixLabors.ImageSharp.Size(430, 780) }));
                image.Save(outStream, format);
                var filename = file.Name;
                var fi = new FileInfo(filename);
                var ext = fi.Extension;
                var result = await _uploadService.UploadAsync(new UploadRequest()
                    {
                        Data = outStream.ToArray(),
                        FileName = "T_" + Guid.NewGuid().ToString() + ext,
                        Extension = ext,
                        Folder = model.PassCode,
                        UploadType = UploadType.VisitorPricture
                    });
                model.TripCode = result.Replace("\\", "/");
            }
        }

        Snackbar.Add(L["Upload trip code successfully"], MudBlazor.Severity.Info);

    }
    private async Task UploadTestReportPhoto(InputFileChangeEventArgs e)
    {
        var file = e.File;
        var filestream = file.OpenReadStream();
        var imgstream = new MemoryStream();
        await filestream.CopyToAsync(imgstream);
        imgstream.Position = 0;
        using (var outStream = new MemoryStream())
        {
            using (var image = Image.Load(imgstream, out IImageFormat format))
            {
                image.Mutate(
                   i => i.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new SixLabors.ImageSharp.Size(430, 780) }));
                image.Save(outStream, format);
                var filename = file.Name;
                var fi = new FileInfo(filename);
                var ext = fi.Extension;
                var result = await _uploadService.UploadAsync(new UploadRequest()
                    {
                        Data = outStream.ToArray(),
                        FileName = "R_" + Guid.NewGuid().ToString() + ext,
                        Extension = ext,
                        Folder = model.PassCode,
                        UploadType = UploadType.VisitorPricture
                    });
                model.NucleicAcidTestReport = result.Replace("\\", "/");
            }
        }

        Snackbar.Add(L["Upload test report successfully"], MudBlazor.Severity.Info);

    }

    private async Task Submit()
    {
        await form.Validate();
        if (form.IsValid)
        {
            if (model.Promise != true)
            {
                Snackbar.Add(L["You must promise"], MudBlazor.Severity.Error);
                return;
            }
            if (model.PrivacyPolicy != true)
            {
                Snackbar.Add(L["You must agree"], MudBlazor.Severity.Error);
                return;
            }
            if (string.IsNullOrEmpty(model.Avatar))
            {
                Snackbar.Add(L["You must upload photo"], MudBlazor.Severity.Error);
                return;
            }
            if (string.IsNullOrEmpty(model.HealthCode))
            {
                Snackbar.Add(L["You must upload health code"], MudBlazor.Severity.Error);
                return;
            }
            if (string.IsNullOrEmpty(model.TripCode))
            {
                Snackbar.Add(L["You must upload trip code"], MudBlazor.Severity.Error);
                return;
            }
            await this.generateQrCode();
            var result = await _mediator.Send(model);
            model.Id = result.Data;
            _submited = true;
            _searchQRcode = model.PassCode;
            await  OnSearchQRcode();
            Snackbar.Add(L["Submit successfully"], MudBlazor.Severity.Info);            
        }

    }
    private async Task generateQrCode()
    {
        var qr = QrCode.EncodeText(model.PassCode, QrCode.Ecc.Medium);
        var qrcode = qr.ToPng(15, 5);
        var result = await _uploadService.UploadAsync(new UploadRequest()
            {
                Data = qrcode,
                FileName = "Q_" + Guid.NewGuid().ToString() + ".png",
                Extension = ".png",
                Folder = model.PassCode,
                UploadType = UploadType.VisitorPricture
            });
        model.QrCode = result.Replace("\\", "/");
    }

    }
